Skip to content

fix: anchor Klaviyo proxy endpoint allowlist to the full path shape [] - #11294

Merged
Michael Pineiro (michaelpineirocontentful) merged 6 commits into
fix/klaviyo-oauth-message-handler-origin-checkfrom
fix/klaviyo-proxy-endpoint-allowlist
Sep 14, 2026
Merged

Michael Pineiro (michaelpineirocontentful) merged 6 commits into
fix/klaviyo-oauth-message-handler-origin-checkfrom
fix/klaviyo-proxy-endpoint-allowlist

Conversation

@michaelpineirocontentful

Copy link
Copy Markdown
Contributor

Summary

The Klaviyo proxy function's endpoint allowlist only checked the path segment before the first slash. A value like template-universal-content/../lists passed that check, and the traversal segment let the request reach a Klaviyo API endpoint that was never allowlisted.

Solution

  • Replace the prefix-only check with a pattern anchored to the exact shape the app actually sends: an allowed endpoint name, optionally followed by a single id segment. Anything else is rejected outright.

Context

Third in a small stack of hardening fixes to the Klaviyo app found during a routine security review. Verified the new pattern still matches every endpoint value the frontend currently sends (bare endpoint names and endpoint/{id}), while rejecting traversal and encoded-traversal variants.

Test plan

  • tsc --noEmit passes
  • Functions build (build-functions) succeeds
  • Verified the allowlist pattern against real call sites plus traversal payloads

@wiz-inc-38d59fb8d7

wiz-inc-38d59fb8d7 Bot commented Sep 9, 2026

Copy link
Copy Markdown

Wiz Scan Summary

Scanner Findings
Vulnerability Finding Vulnerabilities -
Data Finding Sensitive Data -
Secret Finding Secrets -
IaC Misconfiguration IaC Misconfigurations -
SAST Finding SAST Findings -
Software Management Finding Software Management Findings -
Total -

View scan details in Wiz

To detect these findings earlier in the dev lifecycle, try the Wiz Code extension for VS Code, JetBrains, or Visual Studio.

The OAuth callback popup broadcast its completion message with a
wildcard target origin, so any window that ended up as window.opener
could receive the authorization code and state.

Scope the postMessage call to the app's own origin instead of '*'.
…w messages

The window message listener that completes the OAuth flow accepted
any message posted to the window, regardless of where it came from
or which window sent it.

Reject messages that don't come from the app's own origin, or that
don't come from the popup window this instance actually opened.
The proxy's endpoint allowlist only checked the segment before the
first slash, so a value like "template-universal-content/../lists"
passed the check while the traversal segment let the request reach a
Klaviyo endpoint that was never allowlisted.

Replace the prefix check with a pattern anchored to the exact shape
the app actually sends (an allowed endpoint, optionally followed by a
single id segment), rejecting anything else outright.
Covers exact allowlist matches, an allowlisted endpoint plus a single
id segment, and traversal attempts that previously bypassed the
prefix-only check (verified these fail against the pre-fix code and
pass against the anchored-pattern fix).

Widen the vitest include glob to pick up functions/ tests — the
functions/ directory previously had no test coverage at all.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@michaelpineirocontentful
Michael Pineiro (michaelpineirocontentful) force-pushed the fix/klaviyo-oauth-message-handler-origin-check branch from bcd963b to 1000f1b Compare September 11, 2026 15:08
@michaelpineirocontentful Michael Pineiro (michaelpineirocontentful) changed the title fix: anchor Klaviyo proxy endpoint allowlist to the full path shape fix: anchor Klaviyo proxy endpoint allowlist to the full path shape [] Sep 11, 2026
@michaelpineirocontentful
Michael Pineiro (michaelpineirocontentful) marked this pull request as ready for review September 11, 2026 15:09
Comment thread apps/klaviyo/functions/proxyRequest.ts Outdated
@@ -8,6 +8,7 @@ import type {
const KLAVIYO_API_URL = 'https://a.klaviyo.com/api';
const KLAVIYO_API_REVISION = '2025-04-15';
const ALLOWED_ENDPOINTS = ['template-universal-content', 'images'];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this is no longer used, we can get rid of it

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch — inlined it into the pattern literal directly, no separate binding needed. Fixed in fa7f850.

@david-shibley-contentful david-shibley-contentful left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

one comment, none blocking

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The allowlist check moved to ALLOWED_ENDPOINT_PATTERN; ALLOWED_ENDPOINTS
only survived as an internal building block for that regex. Inline it
directly into the pattern literal instead of keeping a separate binding
nothing else reads.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@michaelpineirocontentful
Michael Pineiro (michaelpineirocontentful) removed this pull request from stack #11296 September 14, 2026 14:09
@michaelpineirocontentful
Michael Pineiro (michaelpineirocontentful) force-pushed the fix/klaviyo-oauth-message-handler-origin-check branch from 1000f1b to 813a28c Compare September 14, 2026 14:09
@michaelpineirocontentful
Michael Pineiro (michaelpineirocontentful) merged commit fa01cfc into fix/klaviyo-oauth-message-handler-origin-check Sep 14, 2026
15 checks passed
@michaelpineirocontentful
Michael Pineiro (michaelpineirocontentful) deleted the fix/klaviyo-proxy-endpoint-allowlist branch September 14, 2026 14:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants